package com.markerhub.common.fileter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.markerhub.common.ResponseCode;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: CORSAuthenticationFilter
 * @Description:
 *
 * 对于跨域的POST请求，浏览器发起POST请求前都会发送一个OPTIONS请求已确定服务器是否可用，
 * OPTIONS请求通过后继续执行POST请求，而shiro自带的权限验证是无法处理OPTIONS请求的，
 * 所以这里需要重写isAccessAllowed方法。
 */
public class CORSAuthenticationFilter extends FormAuthenticationFilter {

    private  ObjectMapper objectMapper =  new  ObjectMapper();//jackson工具

    public CORSAuthenticationFilter() {
        super();
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if(request instanceof HttpServletRequest){
            if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")){
                System.out.println("OPTIONS请求");
                return true;//放行option请求
            }
        }
        //看源码可以知道，这里先会判断是否isAuthenticated，再判断是否已授权，不然就会返回false,再走onAccessDenied
        //登录后就认证+授权了，可以通过这个拦截！
        return super.isAccessAllowed(request, response, mappedValue);
    }

    //没有通过上面验证方法的请求会走到这里被拦住
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setStatus(HttpServletResponse.SC_OK);
        res.setCharacterEncoding("UTF-8");
        res.setContentType("text/html; charset=utf-8");
        PrintWriter writer = res.getWriter();
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", ResponseCode.USER_NOT_LOGGED_IN.code());
        map.put("msg", ResponseCode.USER_NOT_LOGGED_IN.message());
        writer.write(objectMapper.writeValueAsString(map));
        writer.close();
        return false;
    }
}
